<?php
defined('ENTER_ID') or die('Hacking attempt');
/*
 * 系统函数集
 * @date 2016/12/02 wzl
 * 第一种:单个字母的方法,大写即可(除p).例:R,S,M
 * 第二种:多个字母的方法,单个字母开头的,以大写,后接小写.例:Cget(代表curl_get方法)
 * 第三种:多个字母的方法,单词(大于2个字母的单词),整个单词小写,后接一个字母并大写.例:setR(代表设置返回信息set_result)
 */
/**
 * 队列操作
 * @param string $name
 * @param string $value
 * @author: wzl
 * @date: 2017
 * @return bool|Queue|string
 */
function Q($name = '', $value = '')
{
    static $queue = '';
    if (empty($queue))
        $queue = new Queue();
    if ($name === '' && $value === '')
        return $queue;
    if ($value === '')
        return $queue->push($name);
    elseif (is_null($value))
        return $queue->forget($name);
    else
        return $queue->set($name, $value);
}

/**
 * 获取和设置配置参数 支持批量定义,最多支持三层结构
 * @param string|array $name 配置变量
 * @param mixed $value 配置值
 * @param mixed $default 默认值
 * @return mixed
 */
function C($name = null, $value = null, $default = null)
{
    static $_config = array();
    // 无参数时获取所有
    if (empty($name)) {
        return $_config;
    }
    // 优先执行设置获取或赋值
    if (is_string($name)) {
        if (!strpos($name, '.')) {
            $name = strtoupper($name);
            if (is_null($value))
                return isset($_config[$name]) ? $_config[$name] : $default;
            $_config[$name] = $value;
            return null;
        }
        // 二维数组设置和获取支持
        $name = explode('.', $name);
        $name[0] = strtoupper($name[0]);
        if (is_null($value)) {
            if (count($name) == 2) {
                return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : $default;
            } else {
                return isset($_config[$name[0]][$name[1]][$name[2]]) ? $_config[$name[0]][$name[1]][$name[2]] : $default;
            }
        }
        if (count($name) == 2)
            $_config[$name[0]][$name[1]] = $value;
        else
            $_config[$name[0]][$name[1]][$name[2]] = $value;
        return null;
    }
    // 批量设置
    if (is_array($name)) {
        $_config = array_merge($_config, array_change_key_case($name, CASE_UPPER));
        return null;
    }
    return null; // 避免非法参数
}

/**
 * 写LOG
 * @param mix $data 数据 任何类型
 * @param string $memo 标识
 * @param string|boolean $method 传'w'则覆盖,传'a'则续写,也可以传true(追加),false(覆盖)
 * @param string $title TTTLE
 */
function mylog($data, $memo = 'None', $method = 'a', $title = 'Open日志记录', $cacheFile = 'debug')
{
    /*兼容以前的*/
    $isPush = true;
    if (is_bool($method)) {
        $isPush = $method;
    } else {
        if ($method == 'w') {
            $isPush = false;
        }
    }
    MiniDebug::setCacheFile($cacheFile);
    MiniDebug::log($data, $memo, $isPush, $title);
}


/**
 * 日常日志记录
 * @param mix $data 数据 任何类型
 * @param string $memo 标识
 * @param string|boolean $method 传'w'则覆盖,传'a'则续写,也可以传true(追加),false(覆盖)
 */
function mylogger($data, $memo = 'None', $method = "a")
{
    $cacheFile = 'logger/dayL_' . date("Ymd");
    mylog($data, $memo, $method, 'Open日常日志记录', $cacheFile);
}

/**
 * 当机时发生
 */
function _shutdownHandle()
{
    if (error_get_last() == null) return;
    $info = array();
    $info['发生时间'] = date('Y-m-d H:i:s');
    $info['最后错误'] = error_get_last();
    mylogger($info, '_shutdownHandle');
}

/**
 * 异常DEBUG
 * @param type $ex
 */
function _exceptionHandle($ex)
{
    $info = array();
    $info['发生时间'] = date('Y-m-d H:i:s');
    $info['错误号码'] = $ex->getCode();
    $info['异常信息'] = $ex->getMessage();
    $info['发生文件'] = $ex->getFile();
    $info['发生行号'] = $ex->getLine();
    mylogger($info, '_exceptionHandle');
}

/**
 * 错误DEBUG
 * trigger_error 触发
 * @param type $errno
 * @param type $errstr
 * @param type $errfile
 * @param type $errline
 */
function _errorHandle($errno, $errstr, $errfile, $errline)
{
    $info = array();
    $info['发生时间'] = date('Y-m-d H:i:s');
    $info['错误号'] = $errno;
    $info['错误文件'] = $errfile;
    $info['错误行号'] = $errline;
    $info['错误信息'] = $errstr;
    switch ($errno) {
        case 8:
            if (ENV == ENV_ONLINE_PRODUCT)
                break;
        case E_WARNING:
            if (ENV == ENV_ONLINE_PRODUCT)
                break;
        case E_STRICT:
            if (ENV == ENV_ONLINE_PRODUCT)
                break;;
        case E_ERROR:
        case E_PARSE:
        case E_CORE_ERROR:
        case E_COMPILE_ERROR:
        case E_USER_ERROR:
        default:
            mylogger($info, '_errorHandle');
            break;
    }

}


/**
 * 加转义符 函数返回在预定义字符之前添加反斜杠的字符串。
 * @param type $value
 * @return type
 */
function addslashes_deep($value)
{
    if (empty($value))
        return $value;
    else
        return is_array($value) ? array_map('addslashes_deep', $value) : addslashes($value);
}

/**
 * 浏览器友好的变量输出
 * @param mixed $var 变量
 * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串
 * @param string $label 标签 默认为空
 * @param boolean $strict 是否严谨 默认为true
 * @return void|string
 */
function dump($var, $echo = true, $label = null, $strict = true)
{
    $label = ($label === null) ? '' : rtrim($label) . ' ';
    if (!$strict) {
        if (ini_get('html_errors')) {
            $output = print_r($var, true);
            $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
        } else {
            $output = $label . print_r($var, true);
        }
    } else {
        ob_start();
        var_dump($var);
        $output = ob_get_clean();
        if (!extension_loaded('xdebug')) {
            $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
            $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
        }
//        ob_end_clean();
    }
    if ($echo) {
        echo($output);
        return null;
    } else
        return $output;
}

/**
 * 记录和统计时间（微秒）和内存使用情况
 * 用法:
 * 先在某位置:G('start');
 * 最后的位置:G('start', 'end');//统计
 * @param $start
 * @param string $end
 * @author: wzl
 * @date: 2017
 * @return string
 */
function G($start, $end = '')
{//记录运行时间
    static $_info = array();
    static $_mem = array();
    if (!is_float($end) && !empty($end)) { //进行统计信息
        if (!isset($_info[$end])) $_info[$end] = microtime(true);
        if (!isset($_mem[$end])) {
            if (MEMORY_LIMIT_ON) $_mem[$end] = memory_get_usage();
        }
        //计算
        $time = number_format($_info[$end] - $_info[$start], 3);//秒
        $mem = size2mb($_mem[$end] - $_mem[$start], 3);//bit        
        return sprintf('总共耗时:%s秒,消耗内存:%s', $time, $mem);
    } else {
        $_info[$start] = $end ?: microtime(true);
        if (MEMORY_LIMIT_ON) $_mem[$start] = memory_get_usage();
    }
}

/**
 * 将BIT转换成易看的单位
 * @param $size
 * @param int $digits
 * @author: wzl
 * @date: 2017
 * @return string
 */
function size2mb($size, $digits = 2)
{ //digits，要保留几位小数
    $unit = array('', 'K', 'M', 'G', 'T', 'P');//单位数组，是必须1024进制依次的哦。
    $base = 1024;//对数的基数
    $i = floor(log($size, $base));//字节数对1024取对数，值向下取整。
    $n = count($unit);
    if ($i >= $n) {
        $i = $n - 1;
    } elseif ($i <= 0) {
        $i = 0;
    }
    return round($size / pow($base, $i), $digits) . ' ' . $unit[$i] . 'B';
}

/**
 * curl post 支持https, curl_post简写
 * @param $url string 请求url
 * @param array $data 必须是数组　
 * @param int $timeout 超时设置，默认60
 * @author: wzl
 * @date: 2017
 * @return mixed|string
 */
function Cpost($url, array $data, $timeout = 60)
{
    // 模拟提交数据函数
    $params = http_build_query($data);
    $length = strlen($params);
    $curl = curl_init(); // 启动一个CURL会话
    curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
    curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
    curl_setopt($curl, CURLOPT_HTTPHEADER,
        array("Content-Type: application/x-www-form-urlencoded", "Content-length: " . $length));
    curl_setopt($curl, CURLOPT_POSTFIELDS, $params); // Post提交的数据包
    curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); // 设置超时限制防止死循环
    curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
    $result = curl_exec($curl); // 执行操作
    if (curl_errno($curl)) {
        return curl_error($curl);//捕抓异常
    }
    curl_close($curl); // 关闭CURL会话
    return $result; // 返回数据
}

/**
 * curl get 支持https, curl_get简写
 * @param string $url 请求url
 * @param int $timeout 超时设置,默认60秒
 * @return string 返回结果
 */
function Cget($url, $timeout = 60)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_URL, $url);
    $res = curl_exec($curl);
    curl_close($curl);
    return $res;
}

/**
 * 蜘蛛
 * @param type $url
 * @return type
 */
function Cgetf($url)
{
    $ch = curl_init();
    $ip = '115.239.211.112';  //百度蜘蛛
    $timeout = 15;
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    //伪造百度蜘蛛IP  
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:' . $ip . '', 'CLIENT-IP:' . $ip . ''));
    //伪造百度蜘蛛头部
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_REFERER, "http://www.baidu.com/ ");   //构造来路
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    $content = curl_exec($ch);
    return $content;
}

/**
 * 设置返回的结果status|msg
 * @param $status
 * @param $msg
 * @param bool $isJson
 * @param null $extends
 * @author: wzl
 * @date: 2017
 * @return array|string
 */
function setR($status, $msg, $isJson = false, $extends = null)
{
    $result = array(
        'status' => $status,
        'msg' => $msg
    );
    if ($extends != null) {
        if (is_array($extends)) {
            $result = array_merge($result, $extends);
        } else {
            $result['info'] = $extends;
        }
    }
    if ($isJson) {
        return json_encode($result);
    } else {
        return $result;
    }
}

/**
 * 系统提示信息
 * @param $message
 * @param string $title
 * @param string $href
 * @param string $type
 * @param bool $auto_back
 * @author: wzl
 * @date: 2017
 */
function show_message($message, $title = '提示信息', $href = '', $type = 'info', $auto_back = false)
{
    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
        exit(setR(400, $message, true));
    }
    $type_msg = '系统提示信息';
    $type_class = 'panel-primary';
    $a_class = 'btn-success';
    if ($type == 'error') {
        $type_msg = '错误提示信息';
        $type_class = 'panel-danger';
        $a_class = 'btn-danger';
    }
    if (is_bool($href)) {
        $auto_back = $href;
    }
    $href = empty($href) ? 'javascript:window.history.back()' : $href;

    $auto_str = '';
    if ($auto_back) {
        $auto_str = "<meta http-equiv=\"refresh\" content=\"3;URL={$href}\" />";
    }
    $html = <<<__html
<!DOCTYPE html>
<html lang="zh-cn">
    <head>
        <title>{$type_msg}</title>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        {$auto_str}
        <!-- 引入 Bootstrap -->
        <link href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
        <style type="text/css">
            .panel{
                margin:0 350px;
                margin-bottom:5px;
            }
        </style>
    </head>
    <body>
        <div class="panel {$type_class}">
            <div class="panel-heading">
                <h3 class="panel-title">{$title}</h3>
            </div>
            <div class="panel-body">
                {$message}
            </div>
            <div class="panel-footer text-center">
                <a href="{$href}" class="btn {$a_class} btn-block">确认</a>
            </div>
        </div>
    </body>
</html>
__html;
    exit($html);
}